﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Controls;
using GraphosData;
using System.Windows.Threading;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Data;
using System.ComponentModel;

namespace GraphosControls
{
    

	public class VisualNode : Control, INotifyPropertyChanged
	{
        public VisualNode()
        {
            DataContext = this;
            Node = new Node(new Person());
            ResetKeneticValues();
        }

		public VisualNode(Node node)
		{
			DataContext = this;
			Node = node;
            ResetKeneticValues();
		}

        #region Kenetic Properties

        /// <summary>
        /// Gets or sets the velocity of this node
        /// </summary>
        public Vector Velocity { get; set; }

        /// <summary>
        /// Gets or sets the net force for this node
        /// </summary>
        public Vector NetForce { get; set; }

        /// <summary>
        /// Gets or sets the mass for this node
        /// </summary>
        public double Mass { get; set; }

        /// <summary>
        /// Gets or sets the charge for this node
        /// </summary>
        public double Charge { get; set; }

        /// <summary>
        /// Resets all the kenetic node values for positioning
        /// </summary>
        public void ResetKeneticValues()
        {
            Velocity = new Vector(0, 0);
            NetForce = new Vector(0, 0);
            Mass = 1;
            Charge = 125;
        } 

        #endregion

		#region Dependency Properties

		/// <summary>
		/// Gets or sets a boolean identifying if this node is selected or not 
		/// </summary>
		public bool IsSelected
		{
			get { return (bool)GetValue(IsSelectedProperty); }
			set { SetValue(IsSelectedProperty, value); }
		}
		public static readonly DependencyProperty IsSelectedProperty =
			  DependencyProperty.Register("IsSelected", typeof(bool), typeof(VisualNode), 
              new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnIsSelectedChanged)));
        private static void OnIsSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            (sender as VisualNode).UpdateStyles();
        }
        public Point Position
        {
            get { return (Point)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }
        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(Point), typeof(VisualNode),
            new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnPositionChanged)));
        private static void OnPositionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            VisualNode node = sender as VisualNode;
            Point point = (Point)args.NewValue;
            Canvas.SetLeft(node, point.X - node.Center.X);
            Canvas.SetTop(node, point.Y - node.Center.Y);
        } 

		#endregion

		#region Properties

		/// <summary>
		/// Gets the node associated with this VisualNode
		/// </summary>
		public Node Node { get; private set; }

		/// <summary>
		/// Gets or sets the VisualNodes adjacent to this node which are in common with the selected node
		/// </summary>
		public IList<VisualNode> AdjacentVisualNodes { get; set; }

        public Point Center { get; private set; }

        public Brush VisualNodeFillBrush
        {
            get { return GetBrushResource("Fill"); }
        }
        public Brush VisualNodeStrokeBrush
        {
            get { return GetBrushResource("Stroke"); }
        }
        public Brush VisualNodeForegroundBrush
        {
            get { return GetBrushResource("Foreground"); }
        }
        private string State
        {
            get
            {
                string state = string.Empty;
                state += IsSelected ? "Selected" : "";
                state += IsMouseCaptured ? "Captured" : "";
                return state;
            }
        }

		#endregion
		
		#region Overrides

		protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
		{
			// keep the center point up to date when the node changes size
			Center = new Point(sizeInfo.NewSize.Width / 2, sizeInfo.NewSize.Height / 2);
			base.OnRenderSizeChanged(sizeInfo);
		}
        
		protected override void OnInitialized(EventArgs e)
		{
			// set the node style
			Style = (Style)TryFindResource("VisualNodeStyle");
            UpdateStyles();
			base.OnInitialized(e);
		}
        protected override void OnIsMouseCapturedChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnIsMouseCapturedChanged(e);
            UpdateStyles();
        }
		public override string ToString()
		{
			return string.Format("VisualNode: {0}", Node.Person);
		}

        public void UpdateStyles()
        {
            OnPropertyChanged("VisualNodeFillBrush");
            OnPropertyChanged("VisualNodeStrokeBrush");
            OnPropertyChanged("VisualNodeForegroundBrush");
        }

        private Brush GetBrushResource(string type)
        {
            string name = string.Format("{0}{1}{2}Brush",
                Node.Person.Gender.ToString(),
                State,
                type);

            return (Brush)TryFindResource(name);
        }

		#endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string info)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(info));
        }

        #endregion
    }
}

//public class VisualNodeShape : FrameworkElement
//    {
        //    public VisualNodeShape() 
    //        : this(null)
    //    {

    //    }
    //    public VisualNodeShape(Node node) 
    //        : base()
    //    {
    //        DataContext = this;
    //        Node = node;
    //        Velocity = new Vector(0,0);
    //        NetForce = new Vector(0,0);
    //        Mass = 1.0;
    //        Charge = 400;
    //    }

    //    #region Animation Properties
    //    public Vector Velocity { get; set; }
    //    public Vector NetForce { get; set; }
    //    public double Mass { get; set; }
    //    public double Charge { get; set; } 
    //    #endregion

    //    #region Properties

    //    public Brush VisualNodeFill
    //    {
    //        get { return GetBrushResource("Fill"); }   
    //    }
    //    public Brush VisualNodeStroke
    //    {
    //        get { return GetBrushResource("Stroke"); }
    //    }

    //    public Node Node { get; private set; }
    //    public IList<VisualNodeShape> AdjacentVisualNodes { get; private set; }

    //    public Point Position
    //    {
    //        get { return (Point)GetValue(PositionProperty); }
    //        set { SetValue(PositionProperty, value); }
    //    }
    //    public static readonly DependencyProperty PositionProperty =
    //        DependencyProperty.Register("Position", typeof(Point), typeof(VisualNodeShape),
    //        new FrameworkPropertyMetadata(new Point(), FrameworkPropertyMetadataOptions.AffectsArrange));

    //    public bool IsSelected
    //    {
    //        get { return (bool)GetValue(IsSelectedProperty); }
    //        set { SetValue(IsSelectedProperty, value); }
    //    }
    //    public static readonly DependencyProperty IsSelectedProperty =
    //        DependencyProperty.Register("IsSelected", typeof(bool), typeof(VisualNodeShape),
    //        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));



    //    public Geometry Geometry
    //    {
    //        get { return (Geometry)GetValue(GeometryProperty); }
    //        set { SetValue(GeometryProperty, value); }
    //    }

    //    public static readonly DependencyProperty GeometryProperty =
    //        DependencyProperty.Register("Geometry", typeof(Geometry), typeof(VisualNodeShape), new UIPropertyMetadata(new RectangleGeometry()));


    //    #endregion

        
    //    public void AddAdjacentVisualNodes(IList<VisualNodeShape> visualNodes)
    //    {
    //        AdjacentVisualNodes = visualNodes;
    //    }

        
       
    //    public override string ToString()
    //    {
    //        return string.Format("VisualNodeShape: {0}", Node.Person);
    //    }

    //    private Brush GetBrushResource(string type)
    //    {
    //        string name = string.Format("{0}{1}{2}Brush",
    //            Node.Person.Gender == Gender.Male ? "Male" : "Female",
    //            IsSelected ? "Selected" : string.Empty,
    //            type);

    //        return (Brush)TryFindResource(name);
    //    }


       
    //}